package com.gjy.concurrency.lock;

import org.junit.jupiter.api.Test;

import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * @author 宫静雨
 * @version 1.0
 * @since 2023-03-08 10:06:08
 */
public class ConditionTest {

    private static final ReentrantLock LOCK = new ReentrantLock();
    private static final Condition c1 = LOCK.newCondition();
    private static final Condition c2 = LOCK.newCondition();
    private static final Condition c3 = LOCK.newCondition();
    private final AtomicInteger AI = new AtomicInteger(1);

    @Test
    public void test2() {
        ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
        ReentrantReadWriteLock.ReadLock readLock = rwl.readLock();
        ReentrantReadWriteLock.WriteLock writeLock = rwl.writeLock();


    }

    @Test
    public void test1() {

        new Thread(() -> {
            try {
                LOCK.lock();
                if (AI.get() != 2) {
                    c2.await();
                }
                System.out.println(Thread.currentThread().getName() + " B");
                AI.compareAndSet(2, 3);
                c3.signal();
            } catch (Exception e) {
                throw new RuntimeException(e);
            } finally {
                LOCK.unlock();
            }
        }, "B").start();

        new Thread(() -> {
            try {
                LOCK.lock();
                if (AI.get() != 3) {
                    c3.await();
                }
                System.out.println(Thread.currentThread().getName() + " C");
                AI.compareAndSet(3, 1);
                c1.signal();
            } catch (Exception e) {
                throw new RuntimeException(e);
            } finally {
                LOCK.unlock();
            }
        }, "C").start();

        new Thread(() -> {
            try {
                LOCK.lock();
                if (AI.get() != 1) {
                    c1.await();
                }
                System.out.println(Thread.currentThread().getName() + " A");
                AI.compareAndSet(1, 2);
                c2.signal();
            } catch (Exception e) {
                throw new RuntimeException(e);
            } finally {
                LOCK.unlock();
            }
        }, "A").start();

    }
}
